package sg.edu.nus.iss.cats.dataaccess.hibernate;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import sg.edu.nus.iss.cats.dataaccess.UserDAO;
import sg.edu.nus.iss.cats.exception.HibernateAccessLayerException;
import sg.edu.nus.iss.cats.model.Role;
import sg.edu.nus.iss.cats.model.User;

public class UserDAOImpl extends AbstractDao implements UserDAO {

	// Now set its level. Normally you do not need to set the
	// level of a logger programmatically. This is usually done
	// in configuration files.

	public UserDAOImpl() {
		super();
	}

	public User findUser(String userId) throws HibernateAccessLayerException {
		System.out.println("Finding user" + userId);
		try {
			User u = (User) super.find(User.class, userId);
			Role[] userRoles = retrieveRespectiveRoles(u.getUserId());
			for (int i = 0; i < userRoles.length; i++) {
				System.out.println(" results " + userRoles[i].getRoleId()
						+ userRoles[i].getName()
						+ userRoles[i].getDescription());
			}
			u.setRoles(userRoles);
			return u;
		} catch (Throwable t) {
			throw new HibernateAccessLayerException(t.toString());
		}
	}

	public User[] findAllUsers() throws HibernateAccessLayerException {
		try {
			
			List ls = super.findAll(User.class);
			User[] result = new User[ls.size()];
			ls.toArray(result);
			if (result.length > 0) {
				for (int i = 0; i < result.length; i++) {
					result[i].setRoles(retrieveRespectiveRoles(result[i]
							.getUserId()));
				}
			}

			return (result);

		} catch (Throwable t) {

			throw new HibernateAccessLayerException(t.toString());

		}

	}

	public void insertUser(User user) throws HibernateAccessLayerException {
		System.out.println("Inserting user" + user.getUserId());
		try {
			super.saveOrUpdate(user);
		} catch (Throwable t) {
			throw new HibernateAccessLayerException(t.toString());

		}
	}

	public void updateUser(User user) throws HibernateAccessLayerException {

		System.out.println("Updating user" + user.getUserId());
		try {
			super.saveOrUpdate(user);
		} catch (Throwable t) {
			throw new HibernateAccessLayerException(t.toString());

		}

	}

	public void deleteUser(User user) throws HibernateAccessLayerException {
		System.out.println("Deleting user" + user.getUserId());
		try {
			super.delete(user);
		} catch (Throwable t) {
			throw new HibernateAccessLayerException(t.toString());

		}
	}

	public Role[] findAllRoles() throws HibernateAccessLayerException {

		try {
			List ls = super.findAll(Role.class);
			Role[] result = new Role[ls.size()];
			ls.toArray(result);
			return (result);

		} catch (Throwable t) {

			throw new HibernateAccessLayerException(t.toString());

		}

	}

	public Role findRole(String roleId) throws HibernateAccessLayerException {

		try {
			return ((Role) super.find(Role.class, roleId));

		} catch (Throwable t) {
			throw new HibernateAccessLayerException(t.toString());

		}

	}

	public User[] findAllManagers() throws HibernateAccessLayerException {

		Session session = null;
		try {
			// This step will read hibernate.cfg.xml and prepare hibernate for
			// user list
			
			SessionFactory sessionFactory = new Configuration().configure()
					.buildSessionFactory();
			session = sessionFactory.openSession();

			// Create Select Clause HQL
			String hql = "select distinct u from sg.edu.nus.iss.cats.model.User as u, sg.edu.nus.iss.cats.model.UserRole as ur where (u.userId = ur.userId and ur.roleId like \'manager\')";
				
			/*	"SELECT u." + HibernateConstants.u_userId + ", u."
					+ HibernateConstants.u_name + ", u."
					+ HibernateConstants.u_password + ", u."
					+ HibernateConstants.u_employeeId + " FROM "
					+ HibernateConstants.usersTableName + " u, "
					+ HibernateConstants.userRolesTableName + " ur WHERE ur."
					+ HibernateConstants.ur_roleId + "=\'manager\' and ur."
					+ HibernateConstants.ur_userId + "= u."
					+ HibernateConstants.u_userId; */

			List list = session.createQuery(hql).list();
			User[] users = new User[list.size()];
			list.toArray(users);
			
			/*if (!list.equals(null)) {
				System.out.println("User List size is is "+list.size());
				for (int i = 0; i < list.size(); i++) {
					user[i] = (User) (Object) list.get(i); 
					System.out.println("User is "+user[i].getName()); 
					user[i].setRoles(retrieveRespectiveRoles(user[i]
							.getUserId()));
				}
			} */
			session.close();
			return (users);
		} catch (Exception e) {
			System.out.println(e.getMessage());
			throw new HibernateAccessLayerException(e);
		}

	}

	private Role[] retrieveRespectiveRoles(String id)
			throws HibernateAccessLayerException {

		try {

			Role[] userRoles = new UserRoleDAOImpl().findRolesForUser(id);
			for (int i = 0; i < userRoles.length; i++) {
				System.out.println(" results " + userRoles[i].getRoleId()
						+ userRoles[i].getName()
						+ userRoles[i].getDescription());
			}
			return userRoles;
		} catch (Throwable t) {

			throw new HibernateAccessLayerException(t.toString());

		}
	}

}